package com.lou1052.core.util;

import java.lang.reflect.*;

/**
 * Created with IntelliJ IDEA.
 * User: liuqing
 * Date: 12-11-25
 * Time: 下午8:55
 * To change this template use File | Settings | File Templates.
 */
public final class Reflect {
    private Reflect(){}
    public static class Generic{
        /**
         * 获取指定类的泛型参数类型
         * @param clazz  指定的类
         * @param index  第几个泛型参数  从0 开始
         * @return
         */
        public static Class getGenericSupertype(Class clazz, int index) {
            return getComponentType(clazz.getGenericSuperclass(), index);
        }
    }
    public static Class getComponentType(Type type, int index) {
        if (type instanceof Class) {
            Class clazz = (Class) type;
            if (clazz.isArray()) {
                return clazz.getComponentType();
            }
        } else if (type instanceof ParameterizedType) {
            ParameterizedType pt = (ParameterizedType) type;
            Type[] generics = pt.getActualTypeArguments();
            if (index < 0) {
                index = generics.length + index;
            }
            if (index < generics.length) {
                return toClass(generics[index]);
            }
        } else if (type instanceof GenericArrayType) {
            GenericArrayType gat = (GenericArrayType) type;
            return toClass(gat.getGenericComponentType());
        }
        return null;
    }
    public static Class toClass(Type type) {
        if (type instanceof Class) {
            return (Class) type;
        } else if (type instanceof ParameterizedType) {
            ParameterizedType pt = (ParameterizedType) type;
            return toClass(pt.getRawType());
        } else if (type instanceof WildcardType) {
            WildcardType wt = (WildcardType) type;
            Type[] lower = wt.getLowerBounds();
            if (lower.length == 1) {
                return toClass(lower[0]);
            }
            Type[] upper = wt.getUpperBounds();
            if (upper.length == 1) {
                return toClass(upper[0]);
            }
        } else if (type instanceof GenericArrayType) {
            GenericArrayType gat = (GenericArrayType) type;
            Class componentType = toClass(gat.getGenericComponentType());
            // this is sort of stupid but there seems no other way...
            return Array.newInstance(componentType, 0).getClass();
        } else if (type instanceof TypeVariable) {
            TypeVariable tv = (TypeVariable) type;
            Type[] bounds = tv.getBounds();
            if (bounds.length == 1) {
                return toClass(bounds[0]);
            }
        }
        return null;
    }

}
